package plus.lgx.textsearcher.searcher.handler;

import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import plus.lgx.textsearcher.config.SearcherConfig;
import plus.lgx.textsearcher.entity.FileWrapper;
import plus.lgx.textsearcher.entity.PrintData;
import plus.lgx.textsearcher.searcher.extender.Extender;
import plus.lgx.textsearcher.searcher.printer.OutputHandler;
import plus.lgx.textsearcher.util.FileUtil;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Class name: PlainTextFileHandler
 *
 * Create time: 12/14/22 11:10 PM
 *
 * @author lgx
 * @version 1.0
 */
public class PlainTextFileHandler extends AbstractFileHandler {

    private final Extender extender;

    private final String searchContent;

    private final AtomicInteger index = new AtomicInteger();

    PlainTextFileHandler(SearcherConfig config, OutputHandler handler, PrintData data) {
        super(config, handler, data);
        extender = config.extenderEnum.instance(config);
        searchContent = config.searchContent;
        extender.index = index;
    }

    @Override
    @SneakyThrows
    public void handle(FileWrapper wrapper) {
        if ((extender.content = getContent(wrapper)) == null) return;
        extender.off = extender.content.length();
        index.set(-1);

        if (config.searchContentRegex != null)
            extender.m = config.searchContentRegex.matcher(extender.content);
        if (find()) {
            updateFileHead(wrapper);
            updateItem(wrapper);
            handler.printFileHead();
            handler.printItem();
        }
        while (find()) {
            updateItem(wrapper);
            handler.printItem();
        }

        if (wrapper.hasMatched())
            handler.printFileTail();
    }

    private boolean find() {
        index.set(
                config.skip == null
                        ? config.ignoreCase
                                ? StrUtil.indexOfIgnoreCase(extender.content, searchContent, index.get() + 1)
                                : extender.content.indexOf(searchContent, index.get() + 1)
                        : findSkip(index.get() + 1)
        );
        return index.get() >= 0;
    }

    private int findSkip(int startInd) {
        return extender.m.find(startInd) ? extender.m.start() : -1;
    }

    private void updateFileHead(FileWrapper wrapper) {
        data.fileNumber = wrapper.fileNumber;
        data.totalFileNumber = wrapper.totalFileNumber;
        data.fileName = wrapper.file.getName();
        data.filePath = wrapper.file.getAbsolutePath();
        data.fileSize = FileUtil.toFileLength(wrapper.file.length());
    }

    private void updateItem(FileWrapper wrapper) {
        data.itemNumber = wrapper.addAndGetMatchedNumber();
        data.totalItemNumber++;
        data.item = extender.extend();
    }

}
